/**
 * @FileName: StoreQrCode.java
 * @Author
 * @Description:
 * @Date 2016年4月19日 上午11:25:59
 * @CopyRight ZTE Corporation
 */
package cn.hpclub.server.controller.client;

import java.io.File;
import java.io.FileNotFoundException;

import org.apache.commons.lang.StringUtils;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jfinal.aop.Before;
import com.jfinal.core.Controller;
import com.jfinal.ext.interceptor.GET;
import com.jfinal.ext.interceptor.POST;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Model;

import cn.hpclub.server.constant.ClientApiConstant;
import cn.hpclub.server.constant.ClientApiConstant.Msg;
import cn.hpclub.server.constant.ClientApiConstant.ResultCode;
import cn.hpclub.server.interceptor.ClientApiIntercepter;
import cn.hpclub.server.model.MemberOrg;
import cn.hpclub.server.restful.API;
import cn.hpclub.server.service.TokenService;
import cn.hpclub.server.util.SystemConfigUtil;

@API("/StoreServer/PayQrCode")
@Before(value = { ClientApiIntercepter.class })
public class StoreQrCodeController<M extends Model<M>> extends Controller{
    private static final int    SECOND_MOD      = 119;
    private static final int    FIRST_MOD       = 67;
    private static final String QRCODE_URL_PATH = "/api/v1/StoreServer/PayQrCode/downloadQrCode";
    private static final String PATH            = "path";
    private static final String PAY_TYPE        = "payType";
    private static final String ALI_PAY         = "1";
    private static final String WEIXIN_PAY      = "2";
    private static Logger       log             = LoggerFactory.getLogger(StoreQrCodeController.class);

    /**
     * @Title: getPayQrCode
     * @Description:获取用户支付二维码 void
     */
    @Before(value = { POST.class })
    public void getQrCode(){
        String payType = getPara(PAY_TYPE);
        try{
            String username = getUserName();
            checkUserName(username);
            checkPayType(payType);
            int userId = getUserIdByUserName(username);
            getQrCodeFile(username, payType, userId);
            JSONObject data = new JSONObject();
            String hostPrefix = SystemConfigUtil.getSystemConfig().getHostPrefix();
            String contextPath = getRequest().getContextPath();
            data.put(PATH, String.format("%s%s%s", hostPrefix, contextPath, QRCODE_URL_PATH));
            renderJson(getResponseObj(ResultCode.SUCCESS_CODE, Msg.SUCCESS, data).toString());
        }
        catch(InvalidParametersException e){
            e.printStackTrace();
            renderJson(getResponseObj(ResultCode.PARAM_ERROR, e.getMessage(), "").toString());
        }
        catch(FileNotFoundException e){
            e.printStackTrace();
            renderJson(getResponseObj(ResultCode.NOT_EXIST, e.getMessage(), "").toString());
        }
        catch(Exception e){
            e.printStackTrace();
            renderJson(getResponseObj(ResultCode.SERVER_EXCEPTION, Msg.MSG_EXCEPTION, "").toString());
        }
    }

    /**
     * @Title: getUserIdByUserName
     * @Description:根据用户名获取用户Id
     * @param username:用户名
     * @return:用户ID
     * @throws InvalidParametersException
     */
    private int getUserIdByUserName(String username) throws InvalidParametersException{
        log.info("username=" + username);
        MemberOrg member = MemberOrg.dao.getMemberOrgbyUserName(username);
        if(member == null){
            throw new InvalidParametersException("参数错误：用户不存在");
        }
        int userId = member.getInt("id");
        return userId;
    }

    /**
     * @Title: updateQrCode
     * @Description:更新支付二维码图片 void
     */
    @Before(value = { POST.class })
    public void updateQrCode(){
        String username = getUserName();
        String path = getPara(PATH);
        String payType = getPara(PAY_TYPE);
        log.info("username=" + username + ",path=" + path);
        try{
            checkUserName(username);
            checkPayType(payType);
            String sourceFilePath = checkPath(path);
            int userId = getUserIdByUserName(username);
            saveQrCodeFile(username, sourceFilePath, payType, userId);
            renderJson(getResponseObj(ResultCode.SUCCESS_CODE, Msg.SUCCESS, "").toString());
        }
        catch(FileNotFoundException e){
            e.printStackTrace();
            renderJson(getResponseObj(ResultCode.NOT_EXIST, e.getMessage(), "").toString());
        }
        catch(InvalidParametersException e){
            e.printStackTrace();
            renderJson(getResponseObj(ResultCode.PARAM_ERROR, e.getMessage(), "").toString());
        }
        catch(Exception e){
            e.printStackTrace();
            renderJson(getResponseObj(ResultCode.SERVER_EXCEPTION, Msg.MSG_EXCEPTION, "").toString());
        }
    }

    /**
     * @Title: downloadPayQrCode
     * @Description:下载支付二维码图片 void
     */
    @Before(value = { GET.class })
    public void downloadQrCode(){
        String username = getUserName();
        String payType = getPara(PAY_TYPE);
        try{
            checkUserName(username);
            checkPayType(payType);
            int userId = getUserIdByUserName(username);
            File downloadFile = getQrCodeFile(username, payType, userId);
            renderFile(downloadFile);
        }
        catch(InvalidParametersException e){
            e.printStackTrace();
            getResponse().setStatus(400);
        }
        catch(FileNotFoundException e){
            e.printStackTrace();
            getResponse().setStatus(404);
        }
        catch(Exception e){
            e.printStackTrace();
            e.printStackTrace();
            getResponse().setStatus(500);
        }
    }

    /**
     * @Title: getUserName
     * @Description:获取用户名
     * @return String:用户名
     */
    private String getUserName(){
        return TokenService.service.getUsernameByToken(getPara(ClientApiConstant.Key.TOKEN));
    }

    /**
     * @Title: saveQrCodeFile
     * @Description:保存支付二维码图片
     * @param userId:用户ID
     * @param username:帐号
     * @param path:上传文件路径
     * @param payType:支付类型
     *            void
     */
    private void saveQrCodeFile(String username, String path, String payType, int userId){
        String dirPath = getPayQrCodeDirPath(username, userId);
        String destFilePath = String.format("%s/%s.%s", dirPath, payType, getfileExtension(path));
        log.info("destFilePath=" + destFilePath);
        deleteOldFile(username, payType, userId);
        moveSourceFileToDestPath(path, destFilePath);
    }

    /**
     * @Title: deleteOldFile
     * @Description:删除过期的二维码文件
     * @param userId:用户ID
     * @param username:用户名
     * @param payType:支付类型
     *            void
     */
    private void deleteOldFile(String username, String payType, int userId){
        String dirPath = getPayQrCodeDirPath(username, userId);
        File dir = new File(dirPath);
        File[] listFiles = dir.listFiles();
        for(File file : listFiles){
            String fileName = file.getName();
            String name = fileName.substring(0, fileName.lastIndexOf("."));
            if(name.equals(payType)){
                file.delete();
            }
        }
    }

    /**
     * @Title: checkPath
     * @Description:检查上传文件参数，及文件是否存在
     * @param path:上传文件路径
     * @throws InvalidParametersException
     * @throws FileNotFoundException
     *             void
     */
    private String checkPath(String path) throws InvalidParametersException, FileNotFoundException{
        String imageDir = SystemConfigUtil.getSystemConfig().getUploadDir();
        if(StrKit.isBlank(path)){
            throw new InvalidParametersException("参数错误：文件路径为空");
        }
        String subPath = path.substring("/upload".length());
        log.info("subPath=" + subPath);
        log.info("path=" + imageDir + subPath);
        File imageFile = new File(imageDir + subPath);
        if(!imageFile.exists()){
            throw new FileNotFoundException("上传路径文件不存在:" + path);
        }
        return imageFile.getAbsolutePath();
    }

    /**
     * @Title: checkUserName
     * @Description:检查用户名
     * @param username:用户名
     * @throws InvalidParametersException
     *             void
     */
    private void checkUserName(String username) throws InvalidParametersException{
        if(StrKit.isBlank(username)){
            throw new InvalidParametersException("参数错误：帐号为空");
        }
    }

    /**
     * @Title: checkPayType
     * @Description:检查支付类型
     * @param payType:支付类型
     * @throws InvalidParametersException
     *             void
     */
    private void checkPayType(String payType) throws InvalidParametersException{
        if(StrKit.isBlank(payType)){
            throw new InvalidParametersException("参数错误：支付类型为空");
        }

        if(!payType.equals(ALI_PAY) && !payType.equals(WEIXIN_PAY)){
            throw new InvalidParametersException("参数错误：支付类型错误");
        }
    }

    /**
     * @Title: moveSourceFileToDestPath
     * @Description:移动源文件到目标位置
     * @param path:源文件路径
     * @param destFilePath:目标文件路径
     *            void
     */
    private void moveSourceFileToDestPath(String sourceFilePath, String destFilePath){
        File destFile = new File(destFilePath);
        if(destFile.exists()){
            destFile.delete();
        }
        File srcFile = new File(sourceFilePath);
        srcFile.renameTo(destFile);
    }

    /**
     * @Title: getPayQrCodeDirPath
     * @Description:根据用户名获取保存用户支付二维码文件夹路径
     * @param username:用户名
     * @param userId:用户ID
     * @return String
     */
    private String getPayQrCodeDirPath(String username, int userId){
        int firstDirName = userId % FIRST_MOD;
        int SecondeDirName = userId % SECOND_MOD;
        String subDirPath = String.format("D%02d/D%03d/%s", firstDirName, SecondeDirName, username).toUpperCase();

        String rootDir = SystemConfigUtil.getSystemConfig().getPayQrCodeDir();
        String dirPath = String.format("%s/%s", rootDir, subDirPath);

        log.info("filePath=" + dirPath);
        File dir = new File(dirPath);
        if(!dir.exists()){
            dir.mkdirs();
        }
        return dirPath;
    }

    /**
     * @Title: getQrCodeFile
     * @Description:根据用户名和支付类型获取支付二维码
     * @param userId:用户ID
     * @param username:用户名
     * @param payType:支付类型
     * @return:二维码文件对象
     * @throws InvalidParametersException
     * @throws FileNotFoundException
     */
    private File getQrCodeFile(String username, String payType, int userId)
            throws InvalidParametersException, FileNotFoundException{
        String dirPath = getPayQrCodeDirPath(username, userId);
        File dir = new File(dirPath);
        File[] listFiles = dir.listFiles();
        File downloadFile = null;
        for(File file : listFiles){
            String fileName = file.getName();
            String name = fileName.substring(0, fileName.lastIndexOf("."));
            if(name.equals(payType)){
                downloadFile = file;
                break;
            }
        }
        if(downloadFile == null){
            throw new FileNotFoundException("没有找到匹配的二维码文件");
        }
        return downloadFile;
    }

    /**
     * @Title: getfileExtension
     * @Description:获取文件扩展名
     * @param path:文件路径
     * @return String:文件扩展名
     */
    private String getfileExtension(String path){
        String fileExtension = StringUtils.substringAfterLast(path, ".").toLowerCase();
        log.info("fileExtension=" + fileExtension);
        return fileExtension;
    }

    /**
     * @Title: getResponseObj
     * @Description:获取响应的
     * @param code:响应码
     * @param msg:响应消息
     * @param data:扩展数据
     * @return JSONObject
     */
    public JSONObject getResponseObj(int code, String msg, Object data){
        JSONObject rjson = new JSONObject();
        rjson.put(ClientApiConstant.Key.RESULT_CODE, code);
        rjson.put(ClientApiConstant.Key.MESSAGE, msg);
        rjson.put(ClientApiConstant.Key.DATA, data);
        return rjson;
    }

    static class InvalidParametersException extends Exception{
        private static final long serialVersionUID = -650850718892234191L;

        public InvalidParametersException(String msg){
            super(msg);
        }
    }
}
